#include "lib/decoders/oggvorbis/pvmsourcefactoryoggvorbis.h"
#include "lib/decoders/oggvorbis/pvmvoicesourceoggvorbis.h"

#include "lib/memory/pvmmemory.h"

////////////////////////////////////////////////////////////////////////////////
size_t pvm_ov_factory_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
	int bytesToRead = size*nmemb;
	return ((IPvmInStream*)datasource)->Read(ptr, bytesToRead)/size;
}

int pvm_ov_factory_seek_func(void *datasource, pvm_int64 offset, int whence)
{
	TPvmSeek origin = EPVM_SEEK_CURRENT;
	switch(whence)
	{
	case SEEK_CUR:
		origin = EPVM_SEEK_CURRENT;
		break;
	case SEEK_END:
		origin = EPVM_SEEK_END;
		break;
	case SEEK_SET:
		origin = EPVM_SEEK_BEGIN;
		break;
	}

	pvm_bool seekres = ((IPvmInStream*)datasource)->Seek(offset, origin);
	if(seekres)
		return 1;

	return 0;
}

int pvm_ov_factory_close_func(void* /*datasource*/)
{
	return 0;
}

long pvm_ov_factory_tell_func(void *datasource)
{
	return (long)(((IPvmInStream*)datasource)->Tell());
}

PVMSourceFatcoryOggVorbis::PVMSourceFatcoryOggVorbis()
{
}

PVMSourceFatcoryOggVorbis::~PVMSourceFatcoryOggVorbis()
{
}

pvm_bool PVMSourceFatcoryOggVorbis::CanLoad(IPvmInStream* inStream, pvm_int8** /*startData*/, pvm_int* /*startDataSize*/)
{
	OggVorbis_File vf;
	ov_callbacks factory_ov_callbacks;

	if(inStream->Seekable()==0)
		return false;//non seekable streams are not supported currently

	inStream->Seek(0, EPVM_SEEK_BEGIN);

	factory_ov_callbacks.close_func = pvm_ov_factory_close_func;
	factory_ov_callbacks.read_func = pvm_ov_factory_read_func;
	factory_ov_callbacks.seek_func = pvm_ov_factory_seek_func;
	factory_ov_callbacks.tell_func = pvm_ov_factory_tell_func;

	int testRet = ov_test_callbacks(inStream, &vf, NULL, 0, factory_ov_callbacks);
	ov_clear(&vf);

	inStream->Seek(0, EPVM_SEEK_BEGIN);

	return testRet==0;
}

IPVMVoiceSource* PVMSourceFatcoryOggVorbis::CreateVoiceSource(IPvmInStream* inStream, pvm_int8* /*startData*/, pvm_int /*startDataSize*/)
{
	if(inStream->Seekable()==0)
		return false;//non seekable streams are not supported currently

	inStream->Seek(0, EPVM_SEEK_BEGIN);
	return PVMVoiceSourceOggVorbis::Create(inStream);
}

IPVMSourceFatcory* PVMSourceFatcoryOggVorbis::CreateFactory()
{
	return new PVMSourceFatcoryOggVorbis();
}
